/**
 * interface:接口 描述对象的形状
 */
export { }
interface Speakable {
    name: string;
    speak(): void
}

// 会去约束实例化的方法,下方speakMan必须实例化name和speak方法
let speakMan: Speakable = {
    name: 'zhufeng',
    speak() { }
}

//  行为的抽象
// 关于接口的补充知识：同名的接口可以写多个，类型会自动合并

interface Speakable {
    speak(): void
}

interface Eatable {
    eat(): void
}

class Person implements Speakable, Eatable {
    eat(): void {
        throw new Error("Method not implemented.");
    }
    name!: string;
    speak(): void;
    speak(): void;
    speak(): void;
    speak(): void;
    speak() {
        throw new Error("Method not implemented.");
    }

}


// 任意属性，对象字面量只能指定已知的类型，如果需要添加任意属性,

// interface Person2 {
//     readonly id: number;
//     name: string;
// }

// let p: Person2 = {
//     id: 1,
//     name: 'zhufeng',
//     //  对象文字可以只指定已知属性，并且“age”不在类型“Person2”中。
//     age: 10
// }


// 这时候可以使用 任意属性来解决
interface Person2 {
    readonly id: number;
    name: string;
    [key: string]: any //在此处写入任意属性，即可在下方任意扩展属性(仅指定类型，示例中为字符串方法)
}

let p: Person2 = {
    id: 1,
    name: 'zhufeng',
    age: 10,
    home: 'add',
    11: 22,
}

// 接口的继承

interface Speakable {
    speak(): void
}
// 子接口继承父接口
interface SpeakChinese extends Speakable {
    speakChinese(): void
}
// 类 实现 子接口时，会默认实现父接口方法
class ChineseMan implements SpeakChinese {
    name!: string;
    speakChinese(): void {
        throw new Error("Method not implemented.");
    }
    speak(): void {
        throw new Error("Method not implemented.");
    }
}



// readOnly在接口中的使用,有些值是常量/只读的，所以并不需要内容添加

interface Person3 {
    readonly id: number;
}

let p3: Person3 = {
    id: 1
}
// 报错信息：无法分配到 "id" ，因为它是只读属性。
// p3.id = 2;



// 函数类型接口:接口修饰方法
interface Discount {
    (price: number): number
}

const discount: Discount = (price: number): number => {
    // return price * .8 + '$';  //不能将类型“string”分配给类型“number”。
    return price * .8;
}


// 可索引接口-用接口对数组、对象进行约束
interface User {
    [index: number]: string
}
let user: User = {
    0: '0',
    1: '1',
    // 不能将类型“() => void”分配给类型“string”。
    // 2: function () { }
}
// 不能将类型“number”分配给类型“string”。
// let arr: User = ['1', '2', '3',4];


// 用接口约束类-当使用类来实例化接口时，需要实现接口内的方法
interface Speakable {
    speak(): void
}
// 此时，当我实例化类的时候，需要实现speak方法








// 构造函数类型
class Animal {
    constructor(public name: string) {

    }
}

// 如果是修饰普通函数,加上nwe之后就是用来描述类中的构造函数类型
// interface WithNameClass {
//     // 添加new 是用来描述 类的构造函数
//     new(name: string): Animal
// }
// let wc: WithNameClass = Animal


interface WithNameClass {
    // 不添加new 是用来描述函数的实例
    (name: string): any
}
let wc: WithNameClass = (name: string) => { }

// function createAnimal(clazz: WithNameClass) {
//     return new clazz(name);
// }
// createAnimal(Animal, 'zhufeng')